using System.Collections.Generic;
using UnityEngine;

namespace Voodoo.Utils
{
	public static class ExtensionMethodsList
	{
		public static void Swap<T>(this IList<T> list, int firstIndex, int secondIndex)
		{
			if (list == null)
			{
				Debug.LogWarning("Can't swap indexes, the list is null");
				return;
			}
			if (list.Count <= firstIndex || list.Count <= secondIndex)
			{
				Debug.LogWarning("Can't swap indexes, the list is out of range : " + Mathf.Max(firstIndex, secondIndex) + " > " + list.Count);
				return;
			}
			T value = list[firstIndex];
			list[firstIndex] = list[secondIndex];
			list[secondIndex] = value;
		}

		public static void SwapRange<T>(this IList<T> list, (int start, int end) baseRange, (int start, int end) destRange)
		{
			List<T> list2 = new List<T>(list);
			list2.SwapRange(baseRange, destRange);
			for (int i = 0; i < list2.Count; i++)
			{
				list[i] = list2[i];
			}
		}

		public static void SwapRange<T>(this List<T> list, (int start, int end) baseRange, (int start, int end) destRange)
		{
			if (list == null)
			{
				Debug.LogWarning("Can't swap index range, the list is null");
				return;
			}
			if (list.Count <= baseRange.start || list.Count <= baseRange.end || list.Count <= destRange.start || list.Count <= destRange.end)
			{
				Debug.LogWarning("Can't swap index range, the list is out of range : " + Mathf.Max(Mathf.Max(baseRange.start, baseRange.end), destRange.start, destRange.end) + " > " + list.Count);
				return;
			}
			if (baseRange.end < baseRange.start || destRange.end < destRange.start)
			{
				Debug.LogWarning("Can't swap index range, baseRange.end < baseRange.start OR destRange.end < destRange.start");
				return;
			}
			int count = baseRange.end - baseRange.start + 1;
			int count2 = destRange.end - destRange.start + 1;
			List<T> range = list.GetRange(baseRange.start, count);
			List<T> range2 = list.GetRange(destRange.start, count2);
			if (baseRange.start > destRange.start)
			{
				list.InsertRange(baseRange.start, range2);
				list.RemoveRange(destRange.start, count2);
				list.RemoveRange(baseRange.start, count);
				list.InsertRange(destRange.start, range);
			}
			else
			{
				list.InsertRange(destRange.start, range);
				list.RemoveRange(baseRange.start, count);
				list.RemoveRange(destRange.start, count2);
				list.InsertRange(baseRange.start, range2);
			}
		}

		public static void Shuffle<T>(this IList<T> list)
		{
			if (list == null)
			{
				Debug.LogWarning("Can't shuffle, the list is null");
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				list.Swap(i, Random.Range(0, list.Count));
			}
		}

		public static void Shift<T>(this IList<T> list, int offset)
		{
			List<T> list2 = new List<T>(list);
			list2.Shift(offset);
			for (int i = 0; i < list2.Count; i++)
			{
				list[i] = list2[i];
			}
		}

		public static void Shift<T>(this List<T> list, int offset)
		{
			if (offset == 0)
			{
				return;
			}
			if (list == null)
			{
				Debug.LogWarning("Can't shift, the list is null");
				return;
			}
			offset %= list.Count - 1;
			int num = Mathf.Abs(offset);
			if (num >= list.Count)
			{
				Debug.LogWarning("Can't shift, the list does not have enough elements");
				return;
			}
			int index = ((offset > 0) ? (list.Count - offset) : 0);
			List<T> range = list.GetRange(index, num);
			list.RemoveRange(index, num);
			int index2 = ((offset <= 0) ? list.Count : 0);
			list.InsertRange(index2, range);
		}

		public static T GetRandomValue<T>(this IList<T> list)
		{
			if (list.Count != 0)
			{
				return list[Random.Range(0, list.Count)];
			}
			return default(T);
		}

		public static List<T> GetDistinctRandomValues<T>(this IList<T> source, int amount)
		{
			if (source.Count < amount)
			{
				return null;
			}
			List<T> list = new List<T>(source);
			List<T> list2 = new List<T>();
			for (int i = 0; i < amount; i++)
			{
				T item = list[Random.Range(0, list.Count)];
				list.Remove(item);
				list2.Add(item);
			}
			return list2;
		}

		public static bool ContainsAll<T>(this IList<T> source, List<T> values)
		{
			List<T> list = new List<T>(values);
			foreach (T value in values)
			{
				if (source.Contains(value))
				{
					list.Remove(value);
				}
			}
			return list.Count == 0;
		}

		public static string ToString<T>(this IList<T> list, bool showListContent)
		{
			if (showListContent)
			{
				return "[" + string.Join(",", list) + "]";
			}
			return list.ToString();
		}
	}
}
